[AWS IoT] ポリシー変数で複数のモノをセキュアに管理してみた
AWS IoT Coreのポリシー変数は、単一のポリシーで複数のモノを管理する場合に有用です。ポリシー変数はポリシーが評価される際、実際の値に置き換わります。例えば、ポリシー変数iot:ClientId
は、IoTデバイスがAWS IoT Coreに接続するために指定したクライアントIDに置き換わります。
AWS IoT Core ポリシーについて
AWS IoT Core ポリシーは、IAMポリシーと同じルールで定義するJSONドキュメントです。AWS IoT Coreへの接続やデバイスのシャドウへのアクセスを制限することができます。
例えば、次のようなポリシーを定義します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["iot:Connect"], "Resource": ["arn:aws:iot:ap-northeast-1:<AWSアカウントID>:client/*"] }, { "Effect": "Allow", "Action": ["iot:Publish", "iot:Receive"], "Resource": [ "arn:aws:iot:ap-northeast-1:<AWSアカウントID>:topic/$aws/things/*/shadow/*" ] }, { "Effect": "Allow", "Action": ["iot:Subscribe"], "Resource": [ "arn:aws:iot:ap-northeast-1:<AWSアカウントID>:topicfilter/$aws/things/*/shadow/update" ] } ] }
このポリシーではモノの名前(ThingName)にワイルドカードを使用しています。そのため、このポリシーがアタッチされたクライアント証明書でAWS IoT Coreに接続すると、どのデバイスのシャドウへもアクセスが可能となってしまいます。
デバイスとIoTのモノを1対1にして、シャドウへのアクセスを制限する場合には、デバイスごとに1つのポリシーを作成する方法があります。しかし、デバイスの数に比例してポリシーも増えるので、ポリシーの管理が煩雑になります。
そこで、ポリシー変数の利用を検討することになります。
ポリシー変数を使う
ポリシー変数を使用してポリシードキュメントを定義してみます。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["iot:Connect"], "Resource": ["*"], "Condition": { "Bool": { "iot:Connection.Thing.IsAttached": ["true"] } } }, { "Effect": "Allow", "Action": ["iot:Publish", "iot:Receive"], "Resource": [ "arn:aws:iot:ap-northeast-1:<AWSアカウントID>:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/*" ] }, { "Effect": "Allow", "Action": ["iot:Subscribe"], "Resource": [ "arn:aws:iot:ap-northeast-1:<AWSアカウントID>:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update" ] } ] }
iot:Connection.Thing.IsAttached
は証明書やAmazon Cognito IDがIoTのモノにアタッチされている場合にtrueを返します。この変数を使用して、IoTのモノにアタッチされていない証明書が提示された際に、AWS IoT Coreへの接続を拒否することができます。
iot:Connection.Thing.ThingName
はIoTのモノの名前を返します。モノの名前はAWS IoT Coreへ接続する際のクライアントIDから取得されます。AWS IoTではモノの名前=クライアントIDが推奨されています。
このようにポリシー変数を使用することで、単一のポリシーで複数のモノをセキュアに管理することができます。
自前のデバイス証明書を使用する場合には、X.509証明書のポリシー変数でアクセスを制限することもできます。
動作確認
AWS IoT Coreでポリシーとモノと証明書を作成して、MQTT接続した際の動作を確認します。
ポリシーを作成
AWS IoT Coreのマネジメントコーンソールからポリシーを作成します。
先ほどのポリシー変数を利用したJSONドキュメントを貼り付けます。AWSアカウントIDは差し替えてください。
モノを作成
AWS IoT Coreのマネジメントコーンソールから単一のモノを作成します。
モノの名前を入力して次に進みます。
証明書を作成
モノに証明書を追加します。次の画面が表示されるので「1-Click 証明書作成 (推奨)」で証明書を作成します。
証明書の作成が完了したら、次の画面で証明書や秘密鍵などをダウンロードします。また、証明書を有効化して最初に作成したポリシーをアタッチしておきます。
MQTTで接続
MosquittoというMQTT Brokerを使用して、実際にAWS IoT Coreへ接続をしてみます。
brew install mosquitto
AWS IoT CoreのマネジメントコンソールからAWS IoT Coreへ接続するためのエンドポイントを取得します。
ダウンロードしておいた証明書や秘密鍵の保存先パスとメッセージを入力、AWS IoTに接続してメッセージを送信します。thing-sample
はモノを作成した際の名前に変更してください。
mosquitto_pub \ --cafile amazon-root-ca1.pem \ --cert xxxxxxxxxx-certificate.pem.crt \ --key xxxxxxxxxx-private.pem.key \ -h zzzzzzzzzzzzzz-ats.iot.ap-northeast-1.amazonaws.com \ -p 8883 \ -q 1 \ -t '$aws/things/thing-sample/shadow/update' \ -i thing-sample \ -m '{ "state": { "reported": { "color": "red", "power": "on" } } }' \ -d
メッセージの送信に成功すると次のようなログが出力されます。
Client thing-sample sending CONNECT Client thing-sample received CONNACK (0) Client thing-sample sending PUBLISH (d0, q1, r0, m1, '$aws/things/thing-sample/shadow/update', ... (62 bytes)) Client thing-sample received PUBACK (Mid: 1, RC:0) Client thing-sample sending DISCONNECT
マネジメントコンソールでモノのシャドウを表示すると、送信したメッセージを確認できます。
まとめ
AWS IoTのポリシーでポリシー変数を活用して、アクセス権限の管理を効率化することができました。AWS IoTのドキュメントには他にもポリシー変数を使用したポリシーの例が紹介されているので参考にしてみてください。